import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;

public class AutomatedAdminTracker
{
    private static ArrayList<String> blacklist;
    private static ArrayList<String> donotemail;
    private static ArrayList<String> permissions;
    private static ArrayList<Student> students;
    private static ArrayList<Event> events;
    private static Hashtable<Integer, Student> studentIndex;
    
    private static String title = "cadet";

    public static void main(String[] args)
    {
        System.out.println("|==============================================================|");
        System.out.println("|Welcome to the automated AdminTracker email reporting service!|");
        System.out.println("|==============================================================|");
        System.out.println("Serving Unit Troy NJROTC, Programmed by Quan Nguyen, c/o 2010!");
        System.out.println("\n");
        
        loadInformation();
        
        System.out.println("Retrieving messages from Google Mail server...");
        Message[] messages = MailService.getMessages();
        
        if(messages != null && messages.length > 0)
        {
            System.out.println("Process complete. Now interpreting " + messages.length + " emails...");
            for(int i = 0; i < messages.length; i++)
            {
                processEmail(messages[i]);
                archiveMessage(messages[i]);
            }
        }
        else if (messages != null)
        {
            System.out.println("No messages were found.");
        }  
        else //the messages were "null"
        {
            System.out.println("Unable to retrieve email. Closing program.");
        }
        
        AddressIO.writeList("donotemail.txt", donotemail);
        AddressIO.writeList("blacklist.txt", blacklist);
        AddressIO.writeList("permissions.txt", permissions);
        
        System.out.println("Databases appended and process completed. Thanks!");
        System.out.println("|--------------------------------------------------------------|");
        System.out.println("|Serving Unit Troy NJROTC, Programmed by Quan Nguyen, c/o 2010!|");
        System.out.println("");
    }
    
    private static void loadInformation()
    {
        //loads static information into the fields.
                
        //load database
        System.out.println("Loading databases....");
        StudentReader.readStudents();
        students = StudentReader.getStudents();
        EventReader.readEvents();
        events = EventReader.getEvents();
        System.out.println("Complete.");
        
        //check messages
        //calculate response to each
        //send back  
        System.out.println("Retrieving email blacklist, permissions, do-not-email emails...");
        blacklist = AddressIO.readList("blacklist.txt");
        donotemail = AddressIO.readList("donotemail.txt");
        permissions = AddressIO.readList("permissions.txt");

        System.out.println("Indexing students...");
        studentIndex = new Hashtable<Integer, Student>();
        for(Student s : students)
        {
            studentIndex.put(new Integer(s.getID()), s);
        }
    }
    
    private static void archiveMessage(Message message)
    {
        try
        {
            System.out.println("-----Archiving message....");
            message.setFlag(Flags.Flag.DELETED, true); //in google this archives
        }
        catch (MessagingException e)
        {
            System.out.println("-----Unable to archive message.");
        }
    }
    
    private static void processEmail(Message message)
    {
        MimeMessage msg = ((MimeMessage)message);
        try
        {
            String address = msg.getFrom()[0].toString().substring(msg.getFrom()[0].toString().indexOf("<")+1, msg.getFrom()[0].toString().indexOf(">"));
            if(blacklist.contains(address))
            {
                System.out.println("Received message from " + address + ", whose email address is blacklisted.");
                return;
            }
            //this means we haven't received a malicious message, so...
            System.out.println("Received message with subject: " + msg.getSubject());
            Student student = new Student();
            try
            {
                String subject = msg.getSubject();
                student = studentMatch(subject);
                if(student != null)
                    System.out.println("-----Identified student as: " + student.getName() + " with ID: " + student.getID());
                else
                {   
                    System.out.println("-----Could not find student in databases.");
                    return;
                }
                processContent(student, msg, address);                 
            }
            catch (Exception e)
            {
                System.out.println("-----Person improperly identified self.");
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }  
    }
    
    private static Student studentMatch(String line)
    {
        
        String[] part = line.split(" ");
        if(part.length > 2)
        {
            try
            {
                Student compare = studentIndex.get(new Integer(part[2]));
                if(compare == null)
                    return null;
                if(compare.getLastName().equals(part[0].toUpperCase()) &&
                   compare.getFirstName().equals(part[1].toUpperCase()))
                    return compare;
                else
                    return null;
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }
    
    private static void processContent(Student student, MimeMessage message, String email)
    {
        String content = "";
        try
        {
            if(message.getContentType().indexOf("TEXT/PLAIN") == -1)
            {
                System.out.println("-----Message not text/plain! Instead, it's " + message.getContentType());
                System.out.println("-----Returning message to " + email + "...");
                String errorMessage = "Hello " + title + ",\n\nThe message you have sent is not plain text. Please convert your email to plaintext before sending. "+
                "In Google Mail, you can do this by clicking \"Plain Text\" at the top of the email composition window.";
                MailService.sendMessage(email.toString(), "[AdminTracker] Email Error", errorMessage.toString());
                return;
            }
            else
            {
                content = ((String)message.getContent());
                System.out.println("-----Message: " + content);
                interpretContent(content, email, student);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return;
        }
    }
    
    //Table of commands:
    //help/info/about
    //get my records
    //remove my email
    //get ribbon records
    //get team records
    //get all records
    //stop
    //reset
    
    private static void interpretContent(String content, String email, Student student)
    {
        System.out.println("-----Interpreting content...");
        String result = "";
        if(content.indexOf("help") != -1 || content.indexOf("info") != -1 || content.indexOf("about") != -1)
        {
            System.out.println("-----Content requested: HELP");
            ArrayList<String> message = AddressIO.readList("automessage.txt");
            result = "";
            for(String s : message)
                result = result + s + "\n";
        }
        else if(content.indexOf("remove my email") != -1)
        {
            System.out.println("-----Content requested: REMOVE EMAIL");
            if(!donotemail.contains(email))
                donotemail.add(email);
            result = "Hello "+title+",\n\nYour email has been added to the do-not-email registry. "+
            "You can still get your records, but you won't receive the informational email every time you email us.";
        }
        else if(!donotemail.contains(email))
        {
            sendAutoMessage(email);
            System.out.println("-----User requested that we not email the help message.");
        }
        else if(content.indexOf("get my records") != -1)
        {
            System.out.println("-----Content requested: GET RECORDS");
            result = "Hello "+title+",\n\nYou have requested for the records you have currently stored in AdminTracker."+
            " Your records are current as of this date: " + (new Date()).toString() + ". Please use this as"+
            " evidence of receipt. Your records are as follows:\n\n";
            for(int i = 0; i < events.size(); i++)
            {
                if(student.attended(events.get(i)))
                {
                    result = result + (events.get(i).toString() + ", " + events.get(i).getTable().get(new Integer(student.getID())).toString() + " " + events.get(i).getDataName() + ".\n");
                }
                if(events.get(i).getClass().equals(FieldMeet.class))
                {
                    FieldMeet fm = ((FieldMeet)events.get(i));
                    for(int j = 0; j < fm.getEvents().size(); j++)
                    {
                        if(student.attended(fm.getEvents().get(j)))
                        {
                            result = result + (fm.getEvents().get(j).toString() + ", "
                            + fm.getEvents().get(j).getTable().get(new Integer(student.getID())).toString() + " " + fm.getEvents().get(j).getDataName()+".\n");
                        }
                    }
                }
            }
            System.out.println("-----Record fetch complete.");
        }
        else if(content.indexOf("get this event:") != -1)
        {
            System.out.println("-----Content requested: GET EVENT");
            if(hasPermission(email, "E"))
            {
                result = "Hello "+title+",\n\nYou have requested for the " + content.substring(content.indexOf(":")+1) + " event. "+
                         "The result will display below.\n";
                Event event = getEvent(content.substring(content.indexOf(":")+1));
                if(event != null)
                {
                    System.out.println("-----Event requested: " + event.toString());
                    Enumeration keys = event.getTable().keys();
                    Enumeration values = event.getTable().elements();
                    while(keys.hasMoreElements() && values.hasMoreElements())
                    {
                        Student printing = studentIndex.get(keys.nextElement());
                        result = result + printing.getName() + " went for " + values.nextElement().toString() + " " + event.getDataName() + ".\n";
                    }
                    System.out.println("-----Event fetch complete.");
                }
                else
                {
                    System.out.println("-----Event not found.");
                    result = result + "Sorry, the event was not found. However, here is the list of events currently on record.\n\n";
                    for(Event e : events)
                        result = result + e.getName() + ", which occured on " + e.getDateString() + "\n";
                }
            }
            else
            {
                result = "Hello "+title+",\n\nYou do not have permission to access this function.\n"+
                "Please see the Battalion Roster Officer for more information.";
            }
        }
        else if(content.indexOf("get this student:") != -1)
        {
            String entry = content.substring(content.indexOf(":")+1);
            entry = entry.replaceAll("\n", "");
            entry = entry.replaceAll("\r", "");
            System.out.println("-----Content requested: GET STUDENT");
            if(hasPermission(email, "S"))
            {
                Student getStudent = studentMatch(entry);
                if(getStudent != null)
                {
                    System.out.println("-----Student requested: " + getStudent.getName());
                    result = "Hello "+title+",\n\nYour request for " + entry +
                    " returned the following result:\n\n" + getStudent.toString()+"\n\n";
                    for(int i = 0; i < events.size(); i++)
                    {
                        if(getStudent.attended(events.get(i)))
                        {
                            result = result + (events.get(i).toString() + ", " + events.get(i).getTable().get(new Integer(getStudent.getID())).toString() + " " + events.get(i).getDataName() + ".\n");
                        }
                        if(events.get(i).getClass().equals(FieldMeet.class))
                        {
                            FieldMeet fm = ((FieldMeet)events.get(i));
                            for(int j = 0; j < fm.getEvents().size(); j++)
                            {
                                if(student.attended(fm.getEvents().get(j)))
                                {
                                    result = result + (fm.getEvents().get(j).toString() + ", "
                                    + fm.getEvents().get(j).getTable().get(new Integer(getStudent.getID())).toString() + " " + fm.getEvents().get(j).getDataName()+".\n");
                                }
                            }
                        }
                    }
                }
                else
                {
                    System.out.println("-----Student formatted incorrectly.");
                    result = "Hello "+title+",\n\nYour request for " + entry +
                    " failed because it was not formatted properly. Please keep the format to this: "+
                    " LastName FirstName ID.\n";
                }
            }
            else
            {
                result = "Hello "+title+",\n\nYou do not have permission to access this function.\n"+
                "Please see the Battalion Roster Officer for more information.";
            }
        }
        
        try
        {
            MailService.sendMessage(email, "[AdminTracker] Automated Response", result);
        }
        catch (Exception e)
        {
            System.out.println("-----Unable to send email.");
        }
    }
    
    private static Event getEvent(String name)
    {
        String properName = name.trim();
        properName = properName.toUpperCase();
        for(Event e : events)
        {
            String eventName = e.getName().trim().toUpperCase();
            if(properName.equals(eventName))
                return e;
        }
        return null;
    }
    
    private static boolean hasPermission(String email, String permission)
    {
        String[] permissionList = permission.split("-");
        String permissionEntry = getPermission(email);
        boolean result = true;
        int universal = permissionEntry.indexOf(",U");
        if(universal == -1)
        {
            for(int i = 0; i < permissionList.length; i++)
            {
                boolean pass = permissionEntry.indexOf(permissionList[i]) != -1;
                result = result && pass;
            }
        }
        System.out.println("-----"+email+ (result ? " passed" : " failed") + " the permission check for: " + permission + ".");
        return result;
    }
    
    private static String getPermission(String email)
    {
        for(String s : permissions)
        {
            if(s.indexOf(email) != -1)
                return s.substring(s.indexOf(","), s.indexOf("-X"));
        }
        return "";
    }
    
    private static void sendAutoMessage(String email)
    {
        ArrayList<String> message = AddressIO.readList("automessage.txt");
        String result = "";
        for(String s : message)
            result = result + s + "\n";
        try
        {
            MailService.sendMessage(email, "[AdminTracker] Information", result);
        }
        catch (Exception e)
        {
            System.out.println("-----Tried to send auto message but failed.");
        }
    }
}